home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
xpaint-2.1.1
/
menu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-03
|
8KB
|
310 lines
/* +-------------------------------------------------------------------+ */
/* | Copyright 1992, 1993, David Koblas (koblas@netcom.com) | */
/* | | */
/* | Permission to use, copy, modify, and to distribute this software | */
/* | and its documentation for any purpose is hereby granted without | */
/* | fee, provided that the above copyright notice appear in all | */
/* | copies and that both that copyright notice and this permission | */
/* | notice appear in supporting documentation. There is no | */
/* | representations about the suitability of this software for | */
/* | any purpose. this software is provided "as is" without express | */
/* | or implied warranty. | */
/* | | */
/* +-------------------------------------------------------------------+ */
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/MenuButton.h>
#include <X11/Xaw/SimpleMenu.h>
#include <X11/Xaw/SmeBSB.h>
#include <X11/Xaw/SmeLine.h>
#include <X11/Xaw/Form.h>
#include <stdio.h>
#include "menu.h"
#include "bitmaps/checkmark.xbm"
#include "bitmaps/pullright.xbm"
#define MAX_GROUPS 4
typedef struct group_s {
int size;
Widget group[16];
struct group_s *next;
} GroupList;
typedef struct rightlist_s {
Widget widget;
Widget shell;
struct rightlist_s *next;
} RightList;
static GroupList *groupHead = NULL;
static RightList *rightHead = NULL;
static Pixmap checkBitmap = None, pullBitmap = None;
static void pullRightAction(Widget, XEvent *, String *, Cardinal *);
static GroupList *findGroup(Widget w)
{
GroupList *cur = groupHead;
int i;
if (w == None)
return NULL;
while (cur != NULL) {
for (i = 0; i < cur->size; i++)
if (cur->group[i] == w)
return cur;
cur = cur->next;
}
return NULL;
}
static void initMenu(Widget w)
{
static XtActionsRec act = { "popup-menu-pullright", (XtActionProc)pullRightAction };
if (checkBitmap != None)
return;
checkBitmap = XCreateBitmapFromData(XtDisplay(w),
DefaultRootWindow(XtDisplay(w)),
(char *)checkmark_bits,
checkmark_width, checkmark_height);
pullBitmap = XCreateBitmapFromData(XtDisplay(w),
DefaultRootWindow(XtDisplay(w)),
(char *)pullright_bits,
pullright_width, pullright_height);
XtAppAddActions(XtWidgetToApplicationContext(w), &act, 1);
}
static void destroy(Widget w, XtPointer data, XtPointer junk)
{
XtFree((XtPointer)data);
}
static void pullRightAction(Widget w, XEvent *event, String *params, Cardinal *nparams)
{
Dimension width, height;
int x, y;
RightList *cur;
Widget cw = XawSimpleMenuGetActiveEntry(w);
if (cw == None || event->type != MotionNotify)
return;
x = event->xmotion.x;
y = event->xmotion.y;
XtVaGetValues(w, XtNwidth, &width, XtNheight, &height, NULL);
if (x < 0 || x >= width || y < 0 || y >= height)
return;
/*
** Only the second half of the menu is sensitve to pulls
*/
if (x < width / 2)
return;
for (cur = rightHead; cur != NULL && cur->widget != cw; cur = cur->next);
if (cur == NULL)
return;
x = event->xmotion.x_root - 20;
y = event->xmotion.y_root - 20;
XtVaSetValues(cur->shell, XtNx, x, XtNy, y, NULL);
XtPopup(cur->shell, XtGrabExclusive);
}
static void createItem(Widget parent, PaintMenuItem *item,
Widget groups[MAX_GROUPS])
{
int grp = -1;
Widget entry;
if (item->name[0] == '\0') {
entry = XtVaCreateManagedWidget("seperator",
smeLineObjectClass, parent,
NULL);
} else if (item->flags & MF_CHECK) {
entry = XtVaCreateManagedWidget(item->name,
smeBSBObjectClass, parent,
XtNleftMargin, checkmark_width + 4,
NULL);
} else if (item->right != NULL && item->nright != 0) {
static XtTranslations trans = None, trans2 = None;
int i;
RightList *cur;
String nm;
if (trans == None) {
trans = XtParseTranslationTable("<BtnMotion>: highlight() popup-menu-pullright()");
trans2 = XtParseTranslationTable("<LeaveWindow>: unhighlight() MenuPopdown()\n<BtnUp>: notify() unhighlight() MenuPopdown()\n<BtnMotion>: highlight()");
}
entry = XtVaCreateManagedWidget(item->name,
smeBSBObjectClass, parent,
XtNrightMargin, pullright_width,
XtNrightBitmap, pullBitmap,
NULL);
nm = (String)XtMalloc(strlen(XtName(XtParent(parent))) + strlen(item->name) + 16);
sprintf(nm, "%s-%s-right", XtName(XtParent(parent)), item->name);
item->rightShell = XtVaCreatePopupShell(nm,
simpleMenuWidgetClass, parent,
XtNtranslations, trans2,
NULL);
XtAddCallback(item->rightShell, XtNdestroyCallback, destroy, (XtPointer)nm);
XtOverrideTranslations(parent, trans);
for (i = 0; i < item->nright; i++)
createItem(item->rightShell, &item->right[i], groups);
cur = XtNew(RightList);
cur->shell = item->rightShell;
cur->widget = entry;
cur->next = rightHead;
rightHead = cur;
} else {
entry = XtVaCreateManagedWidget(item->name,
smeBSBObjectClass, parent,
NULL);
}
if (item->flags & MF_GROUP1)
grp = 0;
else if (item->flags & MF_GROUP2)
grp = 1;
else if (item->flags & MF_GROUP3)
grp = 2;
else if (item->flags & MF_GROUP4)
grp = 3;
if (grp != -1) {
GroupList *c = findGroup(groups[grp]);
if (c == NULL) {
/* XXX GroupList entry leaked */
c = XtNew(GroupList);
c->next = groupHead;
groupHead = c;
c->size = 0;
groups[grp] = entry;
}
c->group[c->size++] = entry;
}
if ((item->flags & MF_CHECKON) == MF_CHECKON)
XtVaSetValues(entry, XtNleftBitmap, checkBitmap, NULL);
if (item->callback != NULL)
XtAddCallback(entry, XtNcallback, item->callback, item->data);
item->widget = entry;
}
Widget MenuBarCreate(Widget parent, int nbar, PaintMenuBar bar[])
{
int list, item;
Widget button = None, menu;
Widget prevButton = None;
char menuPopupName[80];
int i;
Widget groups[MAX_GROUPS];
initMenu(parent);
/*
** If there is more than one entry in this bar
** reparent it.
*/
if (nbar > 1)
parent = XtVaCreateManagedWidget("menu",
formWidgetClass, parent,
XtNborderWidth, 0,
XtNbottom, XtChainTop,
XtNright, XtChainLeft,
XtNleft, XtChainLeft,
NULL);
for (list = 0; list < nbar; list++) {
char *nm;
strcpy(menuPopupName, bar[list].name);
strcat(menuPopupName, "Menu");
nm = XtNewString(menuPopupName);
button = XtVaCreateManagedWidget(bar[list].name,
menuButtonWidgetClass, parent,
XtNmenuName, nm,
XtNfromHoriz, prevButton,
NULL);
XtAddCallback(button, XtNdestroyCallback, destroy, (XtPointer)nm);
prevButton = button;
menu = XtCreatePopupShell(menuPopupName,
simpleMenuWidgetClass, button,
NULL, 0);
bar[list].widget = menu;
for (i = 0; i < MAX_GROUPS; i++)
groups[i] = None;
for (item = 0; item < bar[list].nitems; item++)
createItem(menu, &bar[list].items[item], groups);
}
return (nbar > 1) ? parent : button;
}
Widget MenuPopupCreate(Widget parent, int nitems, PaintMenuItem items[])
{
static XtTranslations trans = None;
int i;
Widget menu;
Widget groups[MAX_GROUPS];
for (i = 0; i < MAX_GROUPS; i++)
groups[i] = None;
initMenu(parent);
menu = XtCreatePopupShell("popup-menu",
simpleMenuWidgetClass, parent,
NULL, 0);
if (trans == None)
trans = XtParseTranslationTable("<Btn3Down>: XawPositionSimpleMenu(popup-menu) MenuPopup(popup-menu)");
XtOverrideTranslations(parent, trans);
for (i = 0; i < nitems; i++)
createItem(menu, &items[i], groups);
return menu;
}
void MenuCheckItem(Widget w, Boolean flag)
{
GroupList *c;
if (w == None)
return;
if ((c = findGroup(w)) != NULL) {
int i;
for (i = 0; i < c->size; i++)
XtVaSetValues(c->group[i], XtNleftBitmap, None, NULL);
}
XtVaSetValues(w, XtNleftBitmap, flag ? checkBitmap : None, NULL);
}